package xyz.wbsite.dbtool.javafx.ctrl;

import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.util.Callback;
import javafx.util.converter.DefaultStringConverter;
import xyz.wbsite.dbtool.javafx.po.ApiMethod;
import xyz.wbsite.dbtool.javafx.po.Doc;
import xyz.wbsite.dbtool.javafx.po.DocEnt;
import xyz.wbsite.dbtool.javafx.po.DocParam;
import xyz.wbsite.dbtool.javafx.tool.DocClassReader;
import xyz.wbsite.dbtool.javafx.tool.DocRequestReader;
import xyz.wbsite.dbtool.javafx.tool.DocResponseReader;
import xyz.wbsite.dbtool.javafx.tool.Tool;
import xyz.wbsite.dbtool.javafx.view.DBCheckBoxTableCell;
import xyz.wbsite.dbtool.javafx.tool.FileUtil;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class OptionDocController {

    @FXML
    private TextField modulePath;
    @FXML
    private TextField docPath;
    @FXML
    private Button selectModulePath;
    @FXML
    private Button selectDocPath;
    @FXML
    private Button start;
    @FXML
    private Button cancel;
    @FXML
    private TableView apis;
    @FXML
    private CheckBox AjaxDoc;
    @FXML
    private CheckBox ApiDoc;
    @FXML
    private List<Doc> data = new ArrayList<>();

    public Button getSelectModulePath() {
        return selectModulePath;
    }

    public void setSelectModulePath(Button selectModulePath) {
        this.selectModulePath = selectModulePath;
    }

    public Button getSelectDocPath() {
        return selectDocPath;
    }

    public void setSelectDocPath(Button selectDocPath) {
        this.selectDocPath = selectDocPath;
    }

    public List<Doc> getData() {
        return data;
    }

    public void setData(List<Doc> data) {
        this.data = data;
    }

    public TextField getModulePath() {
        return modulePath;
    }

    public void setModulePath(TextField modulePath) {
        this.modulePath = modulePath;
    }

    public TextField getDocPath() {
        return docPath;
    }

    public void setDocPath(TextField docPath) {
        this.docPath = docPath;
    }

    public Button getStart() {
        return start;
    }

    public void setStart(Button start) {
        this.start = start;
    }

    public Button getCancel() {
        return cancel;
    }

    public void setCancel(Button cancel) {
        this.cancel = cancel;
    }

    public TableView getApis() {
        return apis;
    }

    public void setApis(TableView apis) {
        this.apis = apis;
    }

    public CheckBox getAjaxDoc() {
        return AjaxDoc;
    }

    public void setAjaxDoc(CheckBox ajaxDoc) {
        AjaxDoc = ajaxDoc;
    }

    public CheckBox getApiDoc() {
        return ApiDoc;
    }

    public void setApiDoc(CheckBox apiDoc) {
        ApiDoc = apiDoc;
    }

    public void load() {
        File moduleFile = new File(modulePath.getText());

        data.clear();
        if (moduleFile.exists()) {

            List<File> actionPath = Tool.find(moduleFile, "action");

            if (actionPath.size() == 0) {
                return;
            }

            File ajaxPath = Tool.createPath(actionPath.get(0), "ajax");
            for (File file : ajaxPath.listFiles()) {
                String module = file.getName();
                for (File tar : file.listFiles()) {
                    try {
                        String target = tar.getName().replaceAll("\\.java$", "");
                        if (target.endsWith("Ajax")) {
                            target = target.replaceAll("Ajax$", "");
                        }
                        DocClassReader docClassReader = new DocClassReader(tar);
                        for (ApiMethod apiMethod : docClassReader.getMethodList()) {
                            Doc doc = new Doc();
                            doc.setType("ajax");
                            doc.setModule(module);
                            doc.setTarget(target);
                            doc.setRequest(apiMethod.getRequest());
                            doc.setResponse(apiMethod.getResponse());
                            doc.setMethod(apiMethod.getMethod());

                            List<File> reqFiles = Tool.findRequest(moduleFile, apiMethod.getRequest() + ".java");
                            if (reqFiles.size() == 0) {
                                doc.setError(doc.getError() + "未找到请求");
                            } else if (reqFiles.size() > 1) {
                                doc.setError(doc.getError() + "找到多个请求");
                            } else {
                                DocRequestReader docRequestReader = new DocRequestReader(reqFiles.get(0));
//                                doc.setFind("1".equals(docRequestReader.getFindOrSearchflag()));
                                doc.setTitle(docRequestReader.getClassNote());
                                doc.setReqParams(docRequestReader.getFieldDocList());
                                for (String key : docRequestReader.getEnts().keySet()) {
                                    List<DocParam> docParams = docRequestReader.getEnts().get(key);
                                    DocEnt docEnt = new DocEnt();
                                    docEnt.setEntParams(docParams);
                                    doc.addParams(key.split("#")[1], docEnt);
                                }
                            }

                            List<File> rspfiles = Tool.findResponse(moduleFile, apiMethod.getResponse() + ".java");
                            if (rspfiles.size() == 0) {
                                doc.setError(doc.getError() + "未找到响应");
                            } else if (rspfiles.size() > 1) {
                                doc.setError(doc.getError() + "找到多个响应");
                            } else {
                                DocResponseReader docResponseReader = new DocResponseReader(rspfiles.get(0));
                                doc.setRspParams(docResponseReader.getFieldDocList());
                                for (String key : docResponseReader.getEnts().keySet()) {
                                    List<DocParam> docParams = docResponseReader.getEnts().get(key);
                                    DocEnt docEnt = new DocEnt();
                                    docEnt.setEntParams(docParams);
                                    doc.addParams(key.split("#")[1], docEnt);
                                }
                            }

                            doc.setCheck(true);
                            data.add(doc);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

            File apiPath = Tool.createPath(actionPath.get(0), "api");
            for (File file : apiPath.listFiles()) {
                String module = file.getName();
                for (File tar : file.listFiles()) {
                    try {
                        String target = tar.getName().replaceAll("\\.java$", "");
                        if (target.endsWith("Api$")) {
                            target = target.replaceAll("Api$", "");
                        }
                        DocClassReader docClassReader = new DocClassReader(tar);
                        for (ApiMethod apiMethod : docClassReader.getMethodList()) {
                            Doc doc = new Doc();
                            doc.setType("api");
                            doc.setModule(module);
                            doc.setTarget(target);
                            doc.setRequest(apiMethod.getRequest());
                            doc.setResponse(apiMethod.getResponse());
                            doc.setMethod(apiMethod.getMethod());

                            List<File> reqFiles = Tool.findRequest(moduleFile, apiMethod.getRequest() + ".java");
                            if (reqFiles.size() == 0) {
                                doc.setError(doc.getError() + "未找到请求");
                            } else if (reqFiles.size() > 1) {
                                doc.setError(doc.getError() + "找到多个请求");
                            } else {
                                DocRequestReader docRequestReader = new DocRequestReader(reqFiles.get(0));
//                                doc.setFind("1".equals(docRequestReader.getFindOrSearchflag()));
                                doc.setTitle(docRequestReader.getClassNote());
                                doc.setReqParams(docRequestReader.getFieldDocList());
                                for (String key : docRequestReader.getEnts().keySet()) {
                                    List<DocParam> docParams = docRequestReader.getEnts().get(key);
                                    DocEnt docEnt = new DocEnt();
                                    docEnt.setEntParams(docParams);
                                    doc.addParams(key.split("#")[1], docEnt);
                                }
                            }

                            List<File> rspfiles = Tool.findResponse(moduleFile, apiMethod.getResponse() + ".java");
                            if (rspfiles.size() == 0) {
                                doc.setError(doc.getError() + "未找到响应");
                            } else if (rspfiles.size() > 1) {
                                doc.setError(doc.getError() + "找到多个响应");
                            } else {
                                DocResponseReader docResponseReader = new DocResponseReader(rspfiles.get(0));
                                doc.setRspParams(docResponseReader.getFieldDocList());
                                for (String key : docResponseReader.getEnts().keySet()) {
                                    List<DocParam> docParams = docResponseReader.getEnts().get(key);
                                    DocEnt docEnt = new DocEnt();
                                    docEnt.setEntParams(docParams);
                                    doc.addParams(key.split("#")[1], docEnt);
                                }
                            }

                            doc.setCheck(true);
                            data.add(doc);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

            initData();
        }
        System.out.println();
    }

    public List<String> findEntities(File file) {
        ArrayList<String> strings = new ArrayList<>();

        List<String> list = FileUtil.readFileToLines(file);
        for (String s : list) {
            s = s.trim();

            if (s.matches("private\\s+(.*)\\s+(.*);")) {
                Pattern compile = Pattern.compile("private\\s+(.*)\\s+(.*);");
                Matcher matcher = compile.matcher(s);
                if (matcher.find()) {
                    String group = matcher.group(1);
                    if (!Tool.getJavaField().contains(group)) {
                        strings.add(group);
                    }
                }
            }
        }
        return strings;
    }

    public void initData() {
        apis.setEditable(true);
        apis.setSortPolicy(new Callback<TableView, Boolean>() {
            @Override
            public Boolean call(TableView param) {
                //禁止点击列头排序
                return false;
            }
        });
        ObservableList<TableColumn> columns = apis.getColumns();
        columns.get(0).setCellValueFactory(new PropertyValueFactory("check"));
        columns.get(0).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                final DBCheckBoxTableCell checkBoxTableCell = new DBCheckBoxTableCell();
                DBCheckBoxTableCell.sCallback sCallback = checkBoxTableCell.new sCallback() {
                    @Override
                    public ObservableValue<Boolean> call(Integer param) {
                        super.call(param);
                        if (data.get(param).getCheck()) {
                            return new SimpleBooleanProperty(true);
                        } else {
                            return new SimpleBooleanProperty(false);
                        }
                    }
                };
                checkBoxTableCell.setSelectedStateCallback(sCallback);
                checkBoxTableCell.setOnChangeListener(new ChangeListener<Boolean>() {
                    @Override
                    public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                        int param1 = checkBoxTableCell.getParam();
                        Doc api = data.get(param1);
                        api.setCheck(newValue);
                    }
                });
                return checkBoxTableCell;
            }
        });
        columns.get(1).setCellValueFactory(new PropertyValueFactory("type"));
        columns.get(1).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                TextFieldTableCell textFieldTableCell = new TextFieldTableCell(new DefaultStringConverter()) {
                    @Override
                    public void updateItem(Object item, boolean empty) {
                        super.updateItem(item, empty);
                    }
                };

                textFieldTableCell.setEditable(false);
                return textFieldTableCell;
            }
        });
        columns.get(2).setCellValueFactory(new PropertyValueFactory("module"));
        columns.get(2).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                TextFieldTableCell textFieldTableCell = new TextFieldTableCell(new DefaultStringConverter()) {
                    @Override
                    public void updateItem(Object item, boolean empty) {
                        super.updateItem(item, empty);
                    }
                };

                textFieldTableCell.setEditable(false);
                return textFieldTableCell;
            }
        });
        columns.get(3).setCellValueFactory(new PropertyValueFactory("target"));
        columns.get(3).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                TextFieldTableCell textFieldTableCell = new TextFieldTableCell(new DefaultStringConverter()) {
                    @Override
                    public void updateItem(Object item, boolean empty) {
                        super.updateItem(item, empty);
                    }
                };

                textFieldTableCell.setEditable(false);
                return textFieldTableCell;
            }
        });
        columns.get(4).setCellValueFactory(new PropertyValueFactory("method"));
        columns.get(4).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                TextFieldTableCell textFieldTableCell = new TextFieldTableCell(new DefaultStringConverter()) {
                    @Override
                    public void updateItem(Object item, boolean empty) {
                        super.updateItem(item, empty);
                    }
                };
                textFieldTableCell.setEditable(false);
                return textFieldTableCell;
            }
        });
        columns.get(5).setCellValueFactory(new PropertyValueFactory("error"));
        columns.get(5).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                TextFieldTableCell textFieldTableCell = new TextFieldTableCell(new DefaultStringConverter()) {
                    @Override
                    public void updateItem(Object item, boolean empty) {
                        super.updateItem(item, empty);
                    }
                };
                textFieldTableCell.setEditable(false);
                return textFieldTableCell;
            }
        });
        columns.get(6).setCellValueFactory(new PropertyValueFactory("request"));
        columns.get(6).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                TextFieldTableCell textFieldTableCell = new TextFieldTableCell(new DefaultStringConverter()) {
                    @Override
                    public void updateItem(Object item, boolean empty) {
                        super.updateItem(item, empty);
                    }
                };
                textFieldTableCell.setEditable(false);
                return textFieldTableCell;
            }
        });
        columns.get(7).setCellValueFactory(new PropertyValueFactory("response"));
        columns.get(7).setCellFactory(new Callback<TableColumn, TableCell>() {
            @Override
            public TableCell call(TableColumn param) {
                TextFieldTableCell textFieldTableCell = new TextFieldTableCell(new DefaultStringConverter()) {
                    @Override
                    public void updateItem(Object item, boolean empty) {
                        super.updateItem(item, empty);
                    }
                };
                textFieldTableCell.setEditable(false);
                return textFieldTableCell;
            }
        });
        ObservableList<Doc> ObservableList = FXCollections.observableArrayList();
        ObservableList.addAll(data);
        apis.setItems(ObservableList);
    }
}
